//
//  RealTimeLogWindow.m
//  DualMediation
//
//  Created by YeJary on 2025/6/23.
//

#import "RealTimeLogWindow.h"
#import <UIKit/UIKit.h>
#import <Masonry/Masonry.h>
#import <unistd.h>

// IMLogUtils集成支持
#define IMLOGUTILS_AVAILABLE 1

@interface RealTimeLogWindow () {
    // 实例变量声明
    IMLogLevel _minimumLogLevel;
    NSArray<NSNumber *> *_visibleLogTags;
}

@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UIView *headerView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *closeButton;
@property (nonatomic, strong) UIButton *clearButton;
@property (nonatomic, strong) UIButton *exportButton;
@property (nonatomic, strong) UIButton *searchButton;
@property (nonatomic, strong) UITextView *logTextView;
@property (nonatomic, strong) UIView *footerView;
@property (nonatomic, strong) UILabel *statusLabel;

// 性能优化相关
@property (nonatomic, strong) NSMutableArray<NSString *> *logBuffer;
@property (nonatomic, strong) NSTimer *updateTimer;
@property (nonatomic, assign) NSInteger maxLogLines;
@property (nonatomic, assign) BOOL needsUpdate;
@property (nonatomic, strong) dispatch_queue_t logQueue;

// 控制台(NSLog/stdout/stderr)捕获
@property (nonatomic, strong) NSPipe *consolePipe;
@property (nonatomic, strong) NSFileHandle *consoleReadHandle;
@property (nonatomic, assign) int savedStdout;
@property (nonatomic, assign) int savedStderr;
@property (nonatomic, assign) BOOL consoleCaptureEnabled;

// 显示控制
@property (nonatomic, assign, readwrite) BOOL isVisible;

// 手势支持
@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;
@property (nonatomic, assign) CGPoint lastPanPoint;

// IMLogUtils集成
@property (nonatomic, assign) BOOL imLogMonitoringEnabled;
@property (nonatomic, assign) IMLogLevel minimumLogLevel;
@property (nonatomic, strong, nullable) NSArray<NSNumber *> *visibleLogTags;
@property (nonatomic, assign) BOOL showTimestamp;
@property (nonatomic, assign) BOOL showLevel;
@property (nonatomic, assign) BOOL showTag;
@property (nonatomic, assign) BOOL showThread;
// 移除了文件轮询相关的属性，现在使用IMLogUtils的实时监听

// 用于安全访问的实例变量
@property (nonatomic, assign) BOOL isFullyInitialized;

// 搜索功能相关
@property (nonatomic, strong) UIView *searchContainerView;
@property (nonatomic, strong) UITextField *searchTextField;
@property (nonatomic, strong) UIButton *searchExecuteButton;
@property (nonatomic, strong) UIButton *searchClearButton;
@property (nonatomic, strong) UISwitch *caseSensitiveSwitch;
@property (nonatomic, strong) UILabel *caseSensitiveLabel;
@property (nonatomic, strong) NSMutableArray<NSString *> *searchHistory;
@property (nonatomic, assign) BOOL isSearchMode;
@property (nonatomic, strong) NSMutableArray<NSString *> *originalLogBuffer;
@property (nonatomic, strong) NSString *currentSearchKeyword;
@property (nonatomic, strong) UITableView *searchHistoryTableView;
@property (nonatomic, assign) BOOL isShowingHistory;

@end

@implementation RealTimeLogWindow

#pragma mark - Initialization

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // 首先初始化基础属性和队列
        [self setupPerformanceOptimization];
        // 然后设置UI
        [self setupLogWindow];
    }
    return self;
}

#pragma mark - Public Methods

- (void)show {
    [self showWithAnimation:YES];
}

- (void)hide {
    [self hideWithAnimation:YES];
}

- (void)addLog:(NSString *)message {
    [self addLogMessage:message];
}

#pragma mark - Private Methods

- (void)setupLogWindow {
    self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.6];
    self.isVisible = NO;
    self.alpha = 0.0;
    
    [self createSubviews];
    [self setupGestureRecognizers];
    [self setupConstraints];
}

- (void)createSubviews {
    // 创建容器视图
    self.containerView = [[UIView alloc] init];
    self.containerView.backgroundColor = [UIColor colorWithRed:0.05 green:0.05 blue:0.05 alpha:0.95];
    self.containerView.layer.cornerRadius = 12;
    self.containerView.layer.masksToBounds = YES;
    self.containerView.layer.borderWidth = 1;
    self.containerView.layer.borderColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1.0].CGColor;
    [self addSubview:self.containerView];
    
    // 创建头部视图
    [self createHeaderView];
    
    // 创建搜索界面
    [self createSearchView];
    
    // 创建日志显示区域
    [self createLogDisplayArea];
    
    // 创建底部状态栏
    [self createFooterView];
}

- (void)createHeaderView {
    self.headerView = [[UIView alloc] init];
    self.headerView.backgroundColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0];
    [self.containerView addSubview:self.headerView];
    
    // 标题
    self.titleLabel = [[UILabel alloc] init];
    self.titleLabel.text = @"📊 实时日志监控";
    self.titleLabel.textColor = [UIColor whiteColor];
    self.titleLabel.font = [UIFont boldSystemFontOfSize:16];
    [self.headerView addSubview:self.titleLabel];
    
    // 清除按钮
    self.clearButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [self.clearButton setTitle:@"🗑" forState:UIControlStateNormal];
    [self.clearButton setTitleColor:[UIColor systemYellowColor] forState:UIControlStateNormal];
    self.clearButton.titleLabel.font = [UIFont systemFontOfSize:18];
    [self.clearButton addTarget:self action:@selector(clearButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.headerView addSubview:self.clearButton];
    
    // 搜索按钮
    self.searchButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [self.searchButton setTitle:@"🔍" forState:UIControlStateNormal];
    [self.searchButton setTitleColor:[UIColor systemGreenColor] forState:UIControlStateNormal];
    self.searchButton.titleLabel.font = [UIFont systemFontOfSize:18];
    [self.searchButton addTarget:self action:@selector(searchButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.headerView addSubview:self.searchButton];
    
    // 导出按钮
    self.exportButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [self.exportButton setTitle:@"📤" forState:UIControlStateNormal];
    [self.exportButton setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal];
    self.exportButton.titleLabel.font = [UIFont systemFontOfSize:18];
    [self.exportButton addTarget:self action:@selector(exportButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.headerView addSubview:self.exportButton];
    
    // 关闭按钮
    self.closeButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [self.closeButton setTitle:@"✕" forState:UIControlStateNormal];
    [self.closeButton setTitleColor:[UIColor systemRedColor] forState:UIControlStateNormal];
    self.closeButton.titleLabel.font = [UIFont boldSystemFontOfSize:18];
    [self.closeButton addTarget:self action:@selector(closeButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.headerView addSubview:self.closeButton];
}

- (void)createSearchView {
    // 创建搜索容器视图
    self.searchContainerView = [[UIView alloc] init];
    self.searchContainerView.backgroundColor = [UIColor colorWithRed:0.08 green:0.08 blue:0.08 alpha:1.0];
    self.searchContainerView.layer.borderWidth = 1;
    self.searchContainerView.layer.borderColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0].CGColor;
    self.searchContainerView.hidden = YES; // 默认隐藏
    [self.containerView addSubview:self.searchContainerView];
    
    // 搜索输入框
    self.searchTextField = [[UITextField alloc] init];
    self.searchTextField.backgroundColor = [UIColor colorWithRed:0.15 green:0.15 blue:0.15 alpha:1.0];
    self.searchTextField.textColor = [UIColor whiteColor];
    self.searchTextField.font = [UIFont systemFontOfSize:14];
    self.searchTextField.placeholder = @"输入搜索关键词...";
    self.searchTextField.layer.cornerRadius = 6;
    self.searchTextField.layer.borderWidth = 1;
    self.searchTextField.layer.borderColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1.0].CGColor;
    self.searchTextField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 0)];
    self.searchTextField.leftViewMode = UITextFieldViewModeAlways;
    self.searchTextField.returnKeyType = UIReturnKeySearch;
    self.searchTextField.delegate = self;
    [self.searchTextField addTarget:self action:@selector(searchTextFieldChanged:) forControlEvents:UIControlEventEditingChanged];
    [self.searchTextField addTarget:self action:@selector(searchTextFieldReturn:) forControlEvents:UIControlEventEditingDidEndOnExit];
    [self.searchContainerView addSubview:self.searchTextField];
    
    // 搜索执行按钮
    self.searchExecuteButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [self.searchExecuteButton setTitle:@"搜索" forState:UIControlStateNormal];
    [self.searchExecuteButton setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal];
    self.searchExecuteButton.titleLabel.font = [UIFont systemFontOfSize:14];
    self.searchExecuteButton.backgroundColor = [UIColor colorWithRed:0.15 green:0.15 blue:0.15 alpha:1.0];
    self.searchExecuteButton.layer.cornerRadius = 6;
    self.searchExecuteButton.layer.borderWidth = 1;
    self.searchExecuteButton.layer.borderColor = [UIColor systemBlueColor].CGColor;
    [self.searchExecuteButton addTarget:self action:@selector(executeSearch) forControlEvents:UIControlEventTouchUpInside];
    [self.searchContainerView addSubview:self.searchExecuteButton];
    
    // 清除搜索按钮
    self.searchClearButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [self.searchClearButton setTitle:@"清除" forState:UIControlStateNormal];
    [self.searchClearButton setTitleColor:[UIColor systemOrangeColor] forState:UIControlStateNormal];
    self.searchClearButton.titleLabel.font = [UIFont systemFontOfSize:14];
    self.searchClearButton.backgroundColor = [UIColor colorWithRed:0.15 green:0.15 blue:0.15 alpha:1.0];
    self.searchClearButton.layer.cornerRadius = 6;
    self.searchClearButton.layer.borderWidth = 1;
    self.searchClearButton.layer.borderColor = [UIColor systemOrangeColor].CGColor;
    [self.searchClearButton addTarget:self action:@selector(searchClearButtonTapped) forControlEvents:UIControlEventTouchUpInside];
    [self.searchContainerView addSubview:self.searchClearButton];
    
    // 大小写敏感标签
    self.caseSensitiveLabel = [[UILabel alloc] init];
    self.caseSensitiveLabel.text = @"区分大小写";
    self.caseSensitiveLabel.textColor = [UIColor colorWithRed:0.7 green:0.7 blue:0.7 alpha:1.0];
    self.caseSensitiveLabel.font = [UIFont systemFontOfSize:12];
    [self.searchContainerView addSubview:self.caseSensitiveLabel];
    
    // 大小写敏感开关
    self.caseSensitiveSwitch = [[UISwitch alloc] init];
    self.caseSensitiveSwitch.onTintColor = [UIColor systemGreenColor];
    self.caseSensitiveSwitch.transform = CGAffineTransformMakeScale(0.8, 0.8);
    [self.caseSensitiveSwitch addTarget:self action:@selector(caseSensitiveSwitchChanged:) forControlEvents:UIControlEventValueChanged];
    [self.searchContainerView addSubview:self.caseSensitiveSwitch];
    
    // 搜索历史记录表格
    self.searchHistoryTableView = [[UITableView alloc] init];
    self.searchHistoryTableView.backgroundColor = [UIColor colorWithWhite:0.15 alpha:0.95];
    self.searchHistoryTableView.separatorColor = [UIColor colorWithWhite:0.3 alpha:1.0];
    self.searchHistoryTableView.layer.cornerRadius = 8;
    self.searchHistoryTableView.layer.borderWidth = 1;
    self.searchHistoryTableView.layer.borderColor = [UIColor colorWithWhite:0.3 alpha:1.0].CGColor;
    self.searchHistoryTableView.delegate = self;
    self.searchHistoryTableView.dataSource = self;
    self.searchHistoryTableView.hidden = YES;
    self.searchHistoryTableView.alpha = 0.0;
    [self.searchHistoryTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"HistoryCell"];
    [self.containerView addSubview:self.searchHistoryTableView];
}

- (void)createLogDisplayArea {
    self.logTextView = [[UITextView alloc] init];
    self.logTextView.backgroundColor = [UIColor colorWithRed:0.02 green:0.02 blue:0.02 alpha:1.0];
    self.logTextView.textColor = [UIColor colorWithRed:0.8 green:0.9 blue:0.8 alpha:1.0];
    self.logTextView.font = [UIFont fontWithName:@"Menlo" size:11];
    self.logTextView.editable = NO;
    self.logTextView.showsVerticalScrollIndicator = YES;
    self.logTextView.showsHorizontalScrollIndicator = NO;
    self.logTextView.layer.cornerRadius = 6;
    self.logTextView.layer.borderWidth = 1;
    self.logTextView.layer.borderColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0].CGColor;
    self.logTextView.text = @"📋 实时日志已启动，等待日志输出...\n";
    [self.containerView addSubview:self.logTextView];
}

- (void)createFooterView {
    self.footerView = [[UIView alloc] init];
    self.footerView.backgroundColor = [UIColor colorWithRed:0.08 green:0.08 blue:0.08 alpha:1.0];
    [self.containerView addSubview:self.footerView];
    
    self.statusLabel = [[UILabel alloc] init];
    self.statusLabel.text = @"📊 日志行数: 0 | 📱 内存: 正常 | ⚡ 状态: 就绪";
    self.statusLabel.textColor = [UIColor colorWithRed:0.7 green:0.7 blue:0.7 alpha:1.0];
    self.statusLabel.font = [UIFont systemFontOfSize:12];
    [self.footerView addSubview:self.statusLabel];
}

- (void)setupGestureRecognizers {
    // 拖拽手势
    self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
    [self.headerView addGestureRecognizer:self.panGesture];
    
    // 点击背景关闭
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backgroundTapped:)];
    tapGesture.cancelsTouchesInView = NO; // 不拦截子视图按钮点击
    [self addGestureRecognizer:tapGesture];
}

- (void)setupConstraints {
    // 使用Masonry进行约束设置
    [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.mas_equalTo(350);
        make.height.mas_equalTo(500);
    }];
    
    [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.leading.trailing.equalTo(self.containerView);
        make.height.mas_equalTo(44);
    }];
    
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.headerView);
        make.leading.equalTo(self.headerView).offset(16);
    }];
    
    [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.headerView);
        make.trailing.equalTo(self.headerView).offset(-16);
        make.size.mas_equalTo(CGSizeMake(30, 30));
    }];
    
    [self.exportButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.headerView);
        make.trailing.equalTo(self.closeButton.mas_leading).offset(-8);
        make.size.mas_equalTo(CGSizeMake(30, 30));
    }];
    
    [self.searchButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.headerView);
        make.trailing.equalTo(self.exportButton.mas_leading).offset(-8);
        make.size.mas_equalTo(CGSizeMake(30, 30));
    }];
    
    [self.clearButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.headerView);
        make.trailing.equalTo(self.searchButton.mas_leading).offset(-8);
        make.size.mas_equalTo(CGSizeMake(30, 30));
    }];
    
    [self.footerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.trailing.bottom.equalTo(self.containerView);
        make.height.mas_equalTo(32);
    }];
    
    [self.logTextView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.searchContainerView.mas_bottom).offset(8);
        make.leading.equalTo(self.containerView).offset(12);
        make.trailing.equalTo(self.containerView).offset(-12);
        make.bottom.equalTo(self.footerView.mas_top).offset(-8);
    }];
    
    [self.statusLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.footerView);
        make.leading.equalTo(self.footerView).offset(12);
        make.trailing.equalTo(self.footerView).offset(-12);
    }];
    
    // 搜索界面约束
    [self setupSearchConstraints];
}

- (void)setupSearchConstraints {
    // 搜索容器约束
    [self.searchContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.headerView.mas_bottom);
        make.leading.trailing.equalTo(self.containerView);
        make.height.mas_equalTo(80);
    }];
    
    // 搜索输入框约束
    [self.searchTextField mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.searchContainerView).offset(8);
        make.leading.equalTo(self.searchContainerView).offset(12);
        make.trailing.equalTo(self.searchExecuteButton.mas_leading).offset(-8);
        make.height.mas_equalTo(32);
    }];
    
    // 搜索按钮约束
    [self.searchExecuteButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.searchContainerView).offset(8);
        make.trailing.equalTo(self.searchClearButton.mas_leading).offset(-8);
        make.width.mas_equalTo(50);
        make.height.mas_equalTo(32);
    }];
    
    // 清除按钮约束
    [self.searchClearButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.searchContainerView).offset(8);
        make.trailing.equalTo(self.searchContainerView).offset(-12);
        make.width.mas_equalTo(50);
        make.height.mas_equalTo(32);
    }];
    
    // 大小写敏感标签约束
    [self.caseSensitiveLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.searchTextField.mas_bottom).offset(8);
        make.leading.equalTo(self.searchContainerView).offset(12);
        make.bottom.equalTo(self.searchContainerView).offset(-8);
    }];
    
    // 大小写敏感开关约束
    [self.caseSensitiveSwitch mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.caseSensitiveLabel);
        make.leading.equalTo(self.caseSensitiveLabel.mas_trailing).offset(8);
    }];
    
    // 搜索历史记录表格约束
    [self.searchHistoryTableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.searchContainerView.mas_bottom).offset(4);
        make.leading.equalTo(self.searchTextField);
        make.trailing.equalTo(self.searchTextField);
        make.height.equalTo(@120);
    }];
}

- (void)setupPerformanceOptimization {
    // 初始化日志缓冲区
    self.logBuffer = [NSMutableArray arrayWithCapacity:1000];
    self.maxLogLines = 1000; // 最大显示1000行日志
    self.needsUpdate = NO;
    
    // 初始化搜索相关属性
    self.searchHistory = [[NSMutableArray alloc] init];
    self.isSearchMode = NO;
    self.originalLogBuffer = [[NSMutableArray alloc] init];
    self.currentSearchKeyword = nil;
    
    // 创建日志处理队列
    self.logQueue = dispatch_queue_create("com.dualmediationsdk.logqueue", DISPATCH_QUEUE_SERIAL);
    
    // 创建定时器，每0.1秒更新一次UI（防止频繁更新导致卡顿）
    // 使用CommonModes，避免在滚动/拖拽等UITrackingRunLoopMode下暂停刷新
    self.updateTimer = [NSTimer timerWithTimeInterval:0.1
                                               target:self
                                             selector:@selector(updateLogDisplay)
                                             userInfo:nil
                                              repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:self.updateTimer forMode:NSRunLoopCommonModes];
    
    // 初始化IMLogUtils集成
    [self setupIMLogIntegration];
}

- (void)setupIMLogIntegration {
    // 设置默认值，直接使用实例变量避免触发setter
    self.imLogMonitoringEnabled = NO;
    _minimumLogLevel = (IMLogLevel)IMLogLevelInfo;
    _visibleLogTags = nil; // nil表示显示所有标签
    self.showTimestamp = YES;
    self.showLevel = YES;
    self.showTag = YES;
    self.showThread = NO;
    
    // 标记为完全初始化
    self.isFullyInitialized = YES;
    
    // 默认开启控制台捕获（可在外部关闭）
    self.consoleCaptureEnabled = YES;
}

#pragma mark - 公共方法

- (void)addLogMessage:(NSString *)message {
    if (!message || message.length == 0) return;
    
    // 确保队列已经初始化
    if (!self.logQueue || !self.logBuffer) {
        return;
    }
    
    // 在后台队列处理日志
    dispatch_async(self.logQueue, ^{
        // 再次检查，确保对象仍然有效
        if (!self.logBuffer) return;
        
        @try {
            // 添加时间戳
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            formatter.dateFormat = @"HH:mm:ss.SSS";
            NSString *timestamp = [formatter stringFromDate:[NSDate date]];
            NSString *logEntry = [NSString stringWithFormat:@"[%@] %@", timestamp, message];
            
            // 添加到缓冲区
            [self.logBuffer addObject:logEntry];
            
            // 保持最大行数限制
            if (self.logBuffer.count > self.maxLogLines) {
                [self.logBuffer removeObjectsInRange:NSMakeRange(0, self.logBuffer.count - self.maxLogLines)];
            }
            
            // 标记需要更新
            self.needsUpdate = YES;
        } @catch (NSException *exception) {
            [IMLogUtils error:IMLogTagError format:@"Error in addLogMessage: %@", exception.reason];
        }
    });
}

- (void)updateLogDisplay {
    if (!self.needsUpdate || !self.isVisible) return;
    
    dispatch_async(self.logQueue, ^{
        // 构建显示文本
        NSString *displayText = [self.logBuffer componentsJoinedByString:@"\n"];
        NSInteger logCount = self.logBuffer.count;
        
        // 回到主线程更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            self.logTextView.text = displayText;
            
            // 滚动到底部
            if (self.logTextView.text.length > 0) {
                NSRange bottom = NSMakeRange(self.logTextView.text.length - 1, 1);
                [self.logTextView scrollRangeToVisible:bottom];
            }
            
            // 更新状态栏
            [self updateStatusLabel:logCount];
            
            self.needsUpdate = NO;
        });
    });
}

#pragma mark - Console Capture (NSLog/stdout/stderr)

- (BOOL)isIMLogFormattedLine:(NSString *)line {
    // 简单判断是否为IMLogUtils格式，避免重复显示
    // 形如: "yyyy-MM-dd HH:mm:ss.SSS LEVEL [Thread] [TAG] message"
    static NSRegularExpression *regex;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        regex = [NSRegularExpression regularExpressionWithPattern:@"^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}\\s+(VERBOSE|DEBUG|INFO|WARNING|ERROR)\\s+\\[[^\\]]+\\]\\s+\\[[^\\]]+\\]" options:0 error:nil];
    });
    return [regex numberOfMatchesInString:line options:0 range:NSMakeRange(0, line.length)] > 0;
}

- (void)startConsoleCaptureIfNeeded {
    if (!self.consoleCaptureEnabled || self.consolePipe) { return; }
    
    @try {
        self.consolePipe = [NSPipe pipe];
        self.consoleReadHandle = [self.consolePipe fileHandleForReading];
        NSFileHandle *writeHandle = [self.consolePipe fileHandleForWriting];
        int writeFD = (int)[writeHandle fileDescriptor];
        
        // 备份原先的stdout/stderr
        self.savedStdout = dup(STDOUT_FILENO);
        self.savedStderr = dup(STDERR_FILENO);
        
        // 重定向到pipe
        dup2(writeFD, STDOUT_FILENO);
        dup2(writeFD, STDERR_FILENO);
        
        __weak typeof(self) weakSelf = self;
        self.consoleReadHandle.readabilityHandler = ^(NSFileHandle *handle) {
            @autoreleasepool {
                NSData *data = [handle availableData];
                if (data.length == 0) { return; }
                NSString *chunk = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                if (chunk.length == 0) { return; }
                
                // 可能包含多行
                NSArray<NSString *> *lines = [chunk componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
                for (NSString *rawLine in lines) {
                    if (rawLine.length == 0) { continue; }
                    // 过滤掉IMLogUtils已经通过监听回调展示过的日志，避免重复
                    if ([weakSelf isIMLogFormattedLine:rawLine]) { continue; }
                    [weakSelf addLogMessage:[NSString stringWithFormat:@"[Console] %@", rawLine]];
                }
            }
        };
    } @catch (NSException *exception) {
        [IMLogUtils warning:IMLogTagGeneral format:@"⚠️ 控制台日志捕获启动失败: %@", exception.reason];
    }
}

- (void)stopConsoleCaptureIfNeeded {
    if (!self.consolePipe) { return; }
    @try {
        self.consoleReadHandle.readabilityHandler = nil;
        [self.consoleReadHandle closeFile];
        [[self.consolePipe fileHandleForWriting] closeFile];
        self.consoleReadHandle = nil;
        self.consolePipe = nil;
        
        // 恢复stdout/stderr
        if (self.savedStdout >= 0) { dup2(self.savedStdout, STDOUT_FILENO); close(self.savedStdout); self.savedStdout = -1; }
        if (self.savedStderr >= 0) { dup2(self.savedStderr, STDERR_FILENO); close(self.savedStderr); self.savedStderr = -1; }
    } @catch (NSException *exception) {
        [IMLogUtils warning:IMLogTagGeneral format:@"⚠️ 控制台日志捕获停止失败: %@", exception.reason];
    }
}

- (void)updateStatusLabel:(NSInteger)logCount {
    // 获取内存使用情况
    NSString *memoryStatus = [self getMemoryStatus];
    
    // 更新状态
    NSString *status = [NSString stringWithFormat:@"📊 日志行数: %ld | 📱 内存: %@ | ⚡ 状态: %@",
                       (long)logCount, memoryStatus, self.isVisible ? @"运行中" : @"暂停"];
    
    self.statusLabel.text = status;
}

- (NSString *)getMemoryStatus {
    // 简化的内存状态检测
    NSProcessInfo *processInfo = [NSProcessInfo processInfo];
    if (processInfo.physicalMemory > 1024 * 1024 * 1024) { // 1GB以上
        return @"充足";
    } else if (processInfo.physicalMemory > 512 * 1024 * 1024) { // 512MB以上
        return @"正常";
    } else {
        return @"紧张";
    }
}

#pragma mark - 显示控制

- (void)showWithAnimation:(BOOL)animated {
    if (self.isVisible) return;
    
    self.isVisible = YES;
    
    if (animated) {
        self.alpha = 0.0;
        self.containerView.transform = CGAffineTransformMakeScale(0.7, 0.7);
        
        [UIView animateWithDuration:0.3
                              delay:0
             usingSpringWithDamping:0.7
              initialSpringVelocity:0.5
                            options:UIViewAnimationOptionCurveEaseInOut
                         animations:^{
                             self.alpha = 1.0;
                             self.containerView.transform = CGAffineTransformIdentity;
                         }
                         completion:^(BOOL finished) {
                             // 延迟添加日志消息，确保完全初始化
                             dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                                 if (self.isFullyInitialized) {
                                     [self addLogMessage:@"🚀 实时日志弹窗已启动"];
                                 }
                             });
                         }];
    } else {
        self.alpha = 1.0;
        // 延迟添加日志消息
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if (self.isFullyInitialized) {
                [self addLogMessage:@"🚀 实时日志弹窗已启动"];
            }
        });
    }
}

- (void)hideWithAnimation:(BOOL)animated {
    if (!self.isVisible) return;
    
    self.isVisible = NO;
    
    if (animated) {
        [UIView animateWithDuration:0.2
                         animations:^{
                             self.alpha = 0.0;
                             self.containerView.transform = CGAffineTransformMakeScale(0.9, 0.9);
                         }
                         completion:^(BOOL finished) {
                             // 移除removeFromSuperview调用，由外部管理
                         }];
    } else {
        self.alpha = 0.0;
        // 移除removeFromSuperview调用，由外部管理
    }
}

- (void)clearLogs {
    [self clearButtonTapped];
}

#pragma mark - 手势处理

- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture {
    CGPoint translation = [gesture translationInView:self];
    
    switch (gesture.state) {
        case UIGestureRecognizerStateBegan:
            self.lastPanPoint = self.containerView.center;
            break;
            
        case UIGestureRecognizerStateChanged:
            self.containerView.center = CGPointMake(self.lastPanPoint.x + translation.x,
                                                   self.lastPanPoint.y + translation.y);
            break;
            
        case UIGestureRecognizerStateEnded:
        case UIGestureRecognizerStateCancelled:
        {
            // 边界检查，确保不会拖拽到屏幕外
            CGRect bounds = self.bounds;
            CGRect containerFrame = self.containerView.frame;
            
            if (containerFrame.origin.x < 0) {
                containerFrame.origin.x = 0;
            }
            if (containerFrame.origin.y < 0) {
                containerFrame.origin.y = 0;
            }
            if (CGRectGetMaxX(containerFrame) > bounds.size.width) {
                containerFrame.origin.x = bounds.size.width - containerFrame.size.width;
            }
            if (CGRectGetMaxY(containerFrame) > bounds.size.height) {
                containerFrame.origin.y = bounds.size.height - containerFrame.size.height;
            }
            
            [UIView animateWithDuration:0.2 animations:^{
                self.containerView.frame = containerFrame;
            }];
            break;
        }
            
        default:
            break;
    }
}

- (void)backgroundTapped:(UITapGestureRecognizer *)gesture {
    CGPoint location = [gesture locationInView:self];
    if (!CGRectContainsPoint(self.containerView.frame, location)) {
        [self closeButtonTapped];
    }
}

#pragma mark - 按钮事件

- (void)closeButtonTapped {
    [self addLogMessage:@"❌ 用户关闭了实时日志弹窗"];
    [self hideWithAnimation:YES];
    
    if (self.onClose) {
        self.onClose();
    }
}

- (void)clearButtonTapped {
    dispatch_async(self.logQueue, ^{
        [self.logBuffer removeAllObjects];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            self.logTextView.text = @"📋 日志已清空，等待新的日志输出...\n";
            [self updateStatusLabel:0];
        });
    });
}

- (void)exportButtonTapped {
    [self addLogMessage:@"📤 开始导出日志..."];

    __weak typeof(self) weakSelf = self;
    [self exportLogsWithSystemLogs:YES completion:^(NSString *filePath, NSError *error) {
        __strong typeof(weakSelf) self = weakSelf;
        if (!self) { return; }

        if (!filePath) {
            NSString *errMsg = error.localizedDescription ?: @"未知错误";
            [self addLogMessage:[NSString stringWithFormat:@"❌ 导出失败: %@", errMsg]];
            return;
        }

        NSURL *fileURL = [NSURL fileURLWithPath:filePath];
        UIActivityViewController *activityVC = [[UIActivityViewController alloc]
                                               initWithActivityItems:@[fileURL]
                                               applicationActivities:nil];

        if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
            activityVC.popoverPresentationController.sourceView = self.exportButton ?: self;
            activityVC.popoverPresentationController.sourceRect = (self.exportButton ?: self).bounds;
        }

        UIViewController *presentingVC = [self dm_topMostViewController];
        if (!presentingVC) {
            // 兜底：尝试使用旧方式
            presentingVC = [UIApplication sharedApplication].delegate.window.rootViewController;
        }

        if (presentingVC) {
            [presentingVC presentViewController:activityVC animated:YES completion:^{
                [self addLogMessage:@"✅ 日志导出完成"];
            }];
        } else {
            [self addLogMessage:@"❌ 未找到可用于展示分享界面的控制器"];
        }
    }];
}

#pragma mark - Helper

- (UIViewController *)dm_topMostViewController {
    UIWindow *keyWindow = nil;
    if (@available(iOS 13.0, *)) {
        for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
            if (scene.activationState == UISceneActivationStateForegroundActive &&
                [scene isKindOfClass:[UIWindowScene class]]) {
                UIWindowScene *windowScene = (UIWindowScene *)scene;
                for (UIWindow *window in windowScene.windows) {
                    if (window.isKeyWindow) { keyWindow = window; break; }
                }
                if (keyWindow) { break; }
            }
        }
    } else {
        keyWindow = [UIApplication sharedApplication].keyWindow;
    }

    if (!keyWindow) {
        keyWindow = [UIApplication sharedApplication].delegate.window;
    }

    UIViewController *topVC = keyWindow.rootViewController;
    if (!topVC) { return nil; }

    while (true) {
        if ([topVC isKindOfClass:[UINavigationController class]]) {
            topVC = ((UINavigationController *)topVC).visibleViewController;
        } else if ([topVC isKindOfClass:[UITabBarController class]]) {
            UIViewController *selected = ((UITabBarController *)topVC).selectedViewController;
            topVC = selected ?: topVC;
        } else if (topVC.presentedViewController) {
            topVC = topVC.presentedViewController;
        } else {
            break;
        }
    }
    return topVC;
}

#pragma mark - 搜索功能事件

- (void)searchButtonTapped {
    self.isSearchMode = !self.isSearchMode;
    
    [UIView animateWithDuration:0.3 animations:^{
        self.searchContainerView.alpha = self.isSearchMode ? 1.0 : 0.0;
        self.searchContainerView.hidden = !self.isSearchMode;
    }];
    
    if (self.isSearchMode) {
        [self.searchTextField becomeFirstResponder];
        [self addLogMessage:@"🔍 搜索模式已开启"];
    } else {
        [self.searchTextField resignFirstResponder];
        [self clearSearchResults];
        [self addLogMessage:@"🔍 搜索模式已关闭"];
    }
}

- (void)searchExecuteButtonTapped {
    NSString *keyword = self.searchTextField.text;
    if (keyword.length == 0) {
        [self addLogMessage:@"⚠️ 请输入搜索关键词"];
        return;
    }
    
    // 添加到搜索历史
    [self addToSearchHistory:keyword];
    
    // 执行搜索
    [self performSearchWithKeyword:keyword caseSensitive:self.caseSensitiveSwitch.isOn];
}

- (void)searchClearButtonTapped {
    [self clearSearchResults];
    self.searchTextField.text = @"";
    [self addLogMessage:@"🧹 搜索结果已清除"];
}

- (void)caseSensitiveSwitchChanged:(UISwitch *)sender {
    if (self.currentSearchKeyword.length > 0) {
        // 如果当前有搜索关键词，重新执行搜索
        [self performSearchWithKeyword:self.currentSearchKeyword caseSensitive:sender.isOn];
    }
}

#pragma mark - 搜索功能实现

- (void)performSearchWithKeyword:(NSString *)keyword caseSensitive:(BOOL)caseSensitive {
    if (keyword.length == 0) {
        return;
    }

    self.currentSearchKeyword = keyword;

    dispatch_async(self.logQueue, ^{
        // 备份原始日志
        if (self.originalLogBuffer.count == 0) {
            self.originalLogBuffer = [self.logBuffer mutableCopy];
        }

        NSMutableArray *searchResults = [NSMutableArray array];
        NSString *searchKeyword = caseSensitive ? keyword : [keyword lowercaseString];

        for (NSString *logLine in self.originalLogBuffer) {
            NSString *searchLine = caseSensitive ? logLine : [logLine lowercaseString];
            if ([searchLine containsString:searchKeyword]) {
                [searchResults addObject:logLine];
            }
        }
        // 在logQueue中更新共享缓冲，避免在主线程修改共享数组
        [self.logBuffer removeAllObjects];
        [self.logBuffer addObjectsFromArray:searchResults];

        // 预先在队列中构建展示文本和数量，保证枚举期间不被其它写操作干扰
        NSString *displayText = nil;
        NSInteger resultCount = searchResults.count;
        if (resultCount > 0) {
            displayText = [searchResults componentsJoinedByString:@"\n"];
        } else {
            displayText = [NSString stringWithFormat:@"🔍 未找到包含 \"%@\" 的日志记录", keyword];
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            // 更新显示的日志内容（使用已经构建好的字符串）
            self.logTextView.text = displayText;
            [self updateStatusLabel:resultCount];

            if (resultCount > 0) {
                [self addLogMessage:[NSString stringWithFormat:@"🔍 搜索完成，找到 %ld 条匹配记录", (long)resultCount]];
                // 实现高亮显示
                [self highlightSearchKeyword:keyword inTextView:self.logTextView caseSensitive:caseSensitive];
            }
        });
    });
}

- (void)clearSearchResults {
    dispatch_async(self.logQueue, ^{
        // 恢复原始日志
        if (self.originalLogBuffer.count > 0) {
            [self.logBuffer removeAllObjects];
            [self.logBuffer addObjectsFromArray:self.originalLogBuffer];
            [self.originalLogBuffer removeAllObjects];
        }

        // 在串行队列中生成快照与展示字符串，避免主线程枚举共享可变数组
        NSArray<NSString *> *snapshot = [self.logBuffer copy];
        NSString *displayText = [snapshot componentsJoinedByString:@"\n"];
        NSInteger count = snapshot.count;

        dispatch_async(dispatch_get_main_queue(), ^{
            self.currentSearchKeyword = @"";

            // 恢复显示（使用快照）
            self.logTextView.text = displayText;
            [self updateStatusLabel:count];

            // 清除高亮
            [self clearHighlight];
        });
    });
}

- (void)highlightSearchKeyword:(NSString *)keyword inTextView:(UITextView *)textView caseSensitive:(BOOL)caseSensitive {
    if (keyword.length == 0 || textView.text.length == 0) {
        return;
    }
    
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:textView.text];
    
    // 设置默认属性
    [attributedText addAttribute:NSForegroundColorAttributeName 
                           value:[UIColor whiteColor] 
                           range:NSMakeRange(0, attributedText.length)];
    [attributedText addAttribute:NSFontAttributeName 
                           value:[UIFont fontWithName:@"Menlo-Regular" size:12] 
                           range:NSMakeRange(0, attributedText.length)];
    
    // 搜索并高亮关键词
    NSString *searchText = caseSensitive ? textView.text : [textView.text lowercaseString];
    NSString *searchKeyword = caseSensitive ? keyword : [keyword lowercaseString];
    
    NSRange searchRange = NSMakeRange(0, searchText.length);
    NSRange foundRange;
    
    while (searchRange.location < searchText.length) {
        foundRange = [searchText rangeOfString:searchKeyword options:0 range:searchRange];
        if (foundRange.location == NSNotFound) {
            break;
        }
        
        // 高亮找到的关键词
        [attributedText addAttribute:NSBackgroundColorAttributeName 
                               value:[UIColor yellowColor] 
                               range:foundRange];
        [attributedText addAttribute:NSForegroundColorAttributeName 
                               value:[UIColor blackColor] 
                               range:foundRange];
        
        // 更新搜索范围
        searchRange.location = foundRange.location + foundRange.length;
        searchRange.length = searchText.length - searchRange.location;
    }
    
    textView.attributedText = attributedText;
}

- (void)clearHighlight {
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:self.logTextView.text];
    
    // 恢复默认样式
    [attributedText addAttribute:NSForegroundColorAttributeName 
                           value:[UIColor whiteColor] 
                           range:NSMakeRange(0, attributedText.length)];
    [attributedText addAttribute:NSFontAttributeName 
                           value:[UIFont fontWithName:@"Menlo-Regular" size:12] 
                           range:NSMakeRange(0, attributedText.length)];
    
    self.logTextView.attributedText = attributedText;
}

- (void)addToSearchHistory:(NSString *)keyword {
    if (keyword.length == 0) {
        return;
    }
    
    // 移除已存在的相同关键词
    [self.searchHistory removeObject:keyword];
    
    // 添加到开头
    [self.searchHistory insertObject:keyword atIndex:0];
    
    // 限制历史记录数量
    if (self.searchHistory.count > 10) {
        [self.searchHistory removeLastObject];
    }
}

#pragma mark - UITextFieldDelegate

- (void)searchTextFieldChanged:(UITextField *)textField {
    // 实时搜索功能 - 当用户输入文本时触发
    NSString *searchText = textField.text;
    
    if (searchText.length == 0) {
        // 如果搜索框为空，清除搜索结果
        [self searchClearButtonTapped];
        return;
    }
    
    // 延迟搜索，避免频繁搜索影响性能
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(performDelayedSearch) object:nil];
    [self performSelector:@selector(performDelayedSearch) withObject:nil afterDelay:0.3];
}

- (void)performDelayedSearch {
    NSString *searchText = self.searchTextField.text;
    if (searchText.length > 0) {
        [self performSearchWithKeyword:searchText caseSensitive:self.caseSensitiveSwitch.isOn];
    }
}

- (void)searchTextFieldReturn:(UITextField *)textField {
    if (textField == self.searchTextField) {
        [self searchExecuteButtonTapped];
        [textField resignFirstResponder];
    }
}

- (void)executeSearch {
    // 执行搜索功能 - 当用户点击搜索执行按钮时触发
    [self searchExecuteButtonTapped];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    if (textField == self.searchTextField) {
        [self searchExecuteButtonTapped];
        return YES;
    }
    return NO;
}

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    if (textField == self.searchTextField && self.searchHistory.count > 0) {
        [self showSearchHistory];
    }
    return YES;
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    if (textField == self.searchTextField) {
        // 延迟隐藏，给用户时间点击历史记录
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self hideSearchHistory];
        });
    }
}

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (tableView == self.searchHistoryTableView) {
        return self.searchHistory.count;
    }
    return 0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (tableView == self.searchHistoryTableView) {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"HistoryCell" forIndexPath:indexPath];
        
        cell.backgroundColor = [UIColor clearColor];
        cell.textLabel.textColor = [UIColor whiteColor];
        cell.textLabel.font = [UIFont systemFontOfSize:14];
        cell.textLabel.text = self.searchHistory[indexPath.row];
        cell.selectionStyle = UITableViewCellSelectionStyleDefault;
        
        // 设置选中背景色
        UIView *selectedBackgroundView = [[UIView alloc] init];
        selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:0.5];
        cell.selectedBackgroundView = selectedBackgroundView;
        
        return cell;
    }
    return nil;
}

#pragma mark - UITableViewDelegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
    if (tableView == self.searchHistoryTableView) {
        NSString *selectedKeyword = self.searchHistory[indexPath.row];
        self.searchTextField.text = selectedKeyword;
        [self hideSearchHistory];
        [self performSearchWithKeyword:selectedKeyword caseSensitive:self.caseSensitiveSwitch.isOn];
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 30.0;
}

#pragma mark - 搜索历史记录管理

- (void)showSearchHistory {
    if (self.searchHistory.count == 0 || self.isShowingHistory) {
        return;
    }
    
    self.isShowingHistory = YES;
    self.searchHistoryTableView.hidden = NO;
    
    [UIView animateWithDuration:0.2 animations:^{
        self.searchHistoryTableView.alpha = 1.0;
    }];
    
    [self.searchHistoryTableView reloadData];
}

- (void)hideSearchHistory {
    if (!self.isShowingHistory) {
        return;
    }
    
    self.isShowingHistory = NO;
    
    [UIView animateWithDuration:0.2 animations:^{
        self.searchHistoryTableView.alpha = 0.0;
    } completion:^(BOOL finished) {
        self.searchHistoryTableView.hidden = YES;
    }];
}

- (void)dealloc {
    [self.updateTimer invalidate];
    self.updateTimer = nil;
    
    // 确保移除IMLogUtils监听器
    if (self.imLogMonitoringEnabled) {
        [IMLogUtils removeLogMonitor];
    }
    // 停止控制台捕获
    [self stopConsoleCaptureIfNeeded];
}

#pragma mark - IMLogUtils Integration

- (void)enableIMLogMonitoring:(BOOL)enable {
    self.imLogMonitoringEnabled = enable;
    
    if (enable) {
        // 使用IMLogUtils的实时监听功能
        [IMLogUtils addLogMonitor:^(NSString *formattedMessage) {
            if (self && [self shouldDisplayLogLine:formattedMessage]) {
                [self addFormattedLogLine:formattedMessage];
            }
        }];
        // 启动控制台(NSLog)捕获，补全第三方/系统日志
        [self startConsoleCaptureIfNeeded];
        
        // 加载现有的日志文件内容
        [self loadCurrentLogFile];
        
        [self addLogMessage:@"🔍 IMLogUtils实时监听已启用"];
    } else {
        [IMLogUtils removeLogMonitor];
        [self stopConsoleCaptureIfNeeded];
        [self addLogMessage:@"⏹ IMLogUtils实时监听已停止"];
    }
}

- (IMLogLevel)minimumLogLevel {
    return _minimumLogLevel;
}

- (void)setMinimumLogLevel:(IMLogLevel)minLevel {
    // 检查对象是否已经完全初始化
    if (!self.isFullyInitialized) {
        // 如果还没初始化完成，只设置值，不发送日志消息
        _minimumLogLevel = minLevel;
        return;
    }
    
    // 安全地设置最小日志级别
    if (minLevel <= IMLogLevelOff) {
        @try {
            _minimumLogLevel = minLevel;
            
            NSString *levelName;
            switch (minLevel) {
                case IMLogLevelVerbose:
                    levelName = @"Verbose";
                    break;
                case IMLogLevelDebug:
                    levelName = @"Debug";
                    break;
                case IMLogLevelInfo:
                    levelName = @"Info";
                    break;
                case IMLogLevelWarning:
                    levelName = @"Warning";
                    break;
                case IMLogLevelError:
                    levelName = @"Error";
                    break;
                case IMLogLevelOff:
                    levelName = @"Off";
                    break;
                default:
                    levelName = [NSString stringWithFormat:@"Unknown(%lu)", (unsigned long)minLevel];
                    break;
            }
            
            // 延迟调用addLogMessage，确保初始化完成
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                if (self.isFullyInitialized) {
                    [self addLogMessage:[NSString stringWithFormat:@"📊 日志级别过滤已设置为: %@", levelName]];
                }
            });
        } @catch (NSException *exception) {
            [IMLogUtils error:IMLogTagError format:@"Error setting minimum log level: %@", exception.reason];
        }
    } else {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if (self.isFullyInitialized) {
                [self addLogMessage:[NSString stringWithFormat:@"❌ 无效的日志级别: %lu", (unsigned long)minLevel]];
            }
        });
    }
}

- (NSArray<NSNumber *> *)visibleLogTags {
    return _visibleLogTags;
}

- (void)setVisibleLogTags:(NSArray<NSNumber *> *)tags {
    // 检查对象是否已经完全初始化
    if (!self.isFullyInitialized) {
        // 如果还没初始化完成，只设置值，不发送日志消息
        _visibleLogTags = tags;
        return;
    }
    
    @try {
        _visibleLogTags = tags;
        
        if (tags) {
            NSMutableArray *tagNames = [NSMutableArray array];
            for (NSNumber *tagNum in tags) {
                NSString *tagName = [NSString stringWithFormat:@"Tag_%@", tagNum];
                [tagNames addObject:tagName];
            }
            // 延迟调用addLogMessage，确保初始化完成
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                if (self.isFullyInitialized) {
                    [self addLogMessage:[NSString stringWithFormat:@"🏷 标签过滤已设置: %@", [tagNames componentsJoinedByString:@", "]]];
                }
            });
        } else {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                if (self.isFullyInitialized) {
                    [self addLogMessage:@"🏷 标签过滤已清除，显示所有标签"];
                }
            });
        }
    } @catch (NSException *exception) {
        [IMLogUtils error:IMLogTagError format:@"Error setting visible log tags: %@", exception.reason];
    }
}

- (void)loadLogFile:(NSString *)filePath {
    NSString *targetFile = filePath ?: [IMLogUtils currentLogFilePath];
    if (!targetFile) {
        [self addLogMessage:@"❌ 无法获取日志文件路径"];
        return;
    }
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        NSString *content = [IMLogUtils getLogFileContent:targetFile];
        if (content) {
            NSArray *lines = [content componentsSeparatedByString:@"\n"];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [self clearLogs];
                [self addLogMessage:[NSString stringWithFormat:@"📁 加载日志文件: %@", [targetFile lastPathComponent]]];
                
                // 逐行添加，应用过滤规则
                for (NSString *line in lines) {
                    if (line.length > 0) {
                        if ([self shouldDisplayLogLine:line]) {
                            [self addFormattedLogLine:line];
                        }
                    }
                }
                
                [self addLogMessage:[NSString stringWithFormat:@"✅ 已加载 %lu 行日志", (unsigned long)lines.count]];
                
                // 日志加载完成
            });
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self addLogMessage:@"❌ 无法读取日志文件内容"];
            });
        }
    });
}

// 新增方法：加载当前日志文件
- (void)loadCurrentLogFile {
    [self loadLogFile:nil];
}

- (void)setLogFormat:(BOOL)showTimestamp showLevel:(BOOL)showLevel showTag:(BOOL)showTag showThread:(BOOL)showThread {
    self.showTimestamp = showTimestamp;
    self.showLevel = showLevel;
    self.showTag = showTag;
    self.showThread = showThread;
    
    NSString *formatInfo = [NSString stringWithFormat:@"📝 日志格式: %@%@%@%@",
                           showTimestamp ? @"时间戳 " : @"",
                           showLevel ? @"级别 " : @"",
                           showTag ? @"标签 " : @"",
                           showThread ? @"线程 " : @""];
    [self addLogMessage:formatInfo];
}

- (void)searchLogs:(NSString *)keyword caseSensitive:(BOOL)caseSensitive {
    if (!keyword || keyword.length == 0) {
        [self addLogMessage:@"❌ 搜索关键词不能为空"];
        return;
    }
    
    dispatch_async(self.logQueue, ^{
        NSMutableArray *matchedLogs = [NSMutableArray array];
        NSStringCompareOptions options = caseSensitive ? 0 : NSCaseInsensitiveSearch;
        
        for (NSString *logLine in self.logBuffer) {
            if ([logLine rangeOfString:keyword options:options].location != NSNotFound) {
                [matchedLogs addObject:logLine];
            }
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [self clearLogs];
            [self addLogMessage:[NSString stringWithFormat:@"🔍 搜索结果 \"%@\" (共%lu条)", keyword, (unsigned long)matchedLogs.count]];
            
            for (NSString *line in matchedLogs) {
                [self addLogMessage:line];
            }
        });
    });
}

// 以流方式导出，避免一次性构建超大字符串导致内存峰值
- (void)exportLogsWithSystemLogs:(BOOL)includeSystemLogs completion:(void(^)(NSString *filePath, NSError *error))completion {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        @autoreleasepool {
            // 目标文件路径（使用临时目录，分享完成后系统可清理）
            NSString *tmpDir = NSTemporaryDirectory();
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            formatter.dateFormat = @"yyyyMMdd_HHmmss";
            NSString *timestamp = [formatter stringFromDate:[NSDate date]];
            NSString *fileName = [NSString stringWithFormat:@"DualMediation_Log_%@.txt", timestamp];
            NSString *filePath = [tmpDir stringByAppendingPathComponent:fileName];

            NSOutputStream *out = [NSOutputStream outputStreamToFileAtPath:filePath append:NO];
            [out open];
            if (out.streamStatus == NSStreamStatusError) {
                NSError *err = out.streamError ?: [NSError errorWithDomain:@"RealTimeLogWindow" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"无法创建导出文件"}];
                dispatch_async(dispatch_get_main_queue(), ^{ if (completion) completion(nil, err); });
                return;
            }

            // 小工具：写入字符串
            BOOL (^writeString)(NSString *) = ^BOOL(NSString *s) {
                NSData *d = [s dataUsingEncoding:NSUTF8StringEncoding];
                const uint8_t *bytes = d.bytes; NSInteger remaining = d.length; NSInteger offset = 0;
                while (remaining > 0) {
                    NSInteger wrote = [out write:&bytes[offset] maxLength:(NSUInteger)remaining];
                    if (wrote <= 0) return NO;
                    remaining -= wrote; offset += wrote;
                }
                return YES;
            };

            // 头信息
            writeString(@"# DualMediation 日志导出\n");
            writeString([NSString stringWithFormat:@"# 导出时间: %@\n", [NSDate date]]);
            writeString([NSString stringWithFormat:@"# 包含系统日志: %@\n\n", includeSystemLogs ? @"是" : @"否"]);

            // 弹窗缓冲日志
            writeString(@"## 弹窗实时日志\n");
            __block NSArray<NSString *> *snapshot = nil;
            dispatch_sync(self.logQueue, ^{ snapshot = [self.logBuffer copy]; });
            for (NSString *line in snapshot) {
                writeString(line);
                writeString(@"\n");
            }

            // 系统日志（IMLogUtils 文件）
            if (includeSystemLogs) {
                writeString(@"\n## IMLogUtils系统日志\n");
                NSArray *logFiles = [IMLogUtils allLogFilePaths];
                const NSUInteger chunk = 64 * 1024; // 64KB
                for (NSString *path in logFiles) {
                    @autoreleasepool {
                        writeString([NSString stringWithFormat:@"### 文件: %@\n", [path lastPathComponent]]);
                        NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:path];
                        if (fh) {
                            while (true) {
                                NSData *data = [fh readDataOfLength:chunk];
                                if (data.length == 0) break;
                                NSInteger remaining = data.length; NSInteger offset = 0; const uint8_t *bytes = data.bytes;
                                while (remaining > 0) {
                                    NSInteger wrote = [out write:&bytes[offset] maxLength:(NSUInteger)remaining];
                                    if (wrote <= 0) { remaining = 0; break; }
                                    remaining -= wrote; offset += wrote;
                                }
                            }
                            [fh closeFile];
                        }
                        writeString(@"\n\n");
                    }
                }
            }

            [out close];

            dispatch_async(dispatch_get_main_queue(), ^{
                if (completion) completion(filePath, nil);
                [self addLogMessage:[NSString stringWithFormat:@"✅ 日志已导出到: %@", fileName]];
            });
        }
    });
}

- (NSDictionary *)getLogStatistics {
    NSMutableDictionary *stats = [NSMutableDictionary dictionary];
    
    // 基本统计
    stats[@"弹窗日志行数"] = @(self.logBuffer.count);
    stats[@"最大缓冲行数"] = @(self.maxLogLines);
    stats[@"IMLogUtils监听状态"] = self.imLogMonitoringEnabled ? @"启用" : @"禁用";
    
    stats[@"最小日志级别"] = [NSString stringWithFormat:@"Level_%lu", (unsigned long)self.minimumLogLevel];
    
    // IMLogUtils统计
    if ([IMLogUtils currentLogFilePath]) {
        stats[@"当前日志文件"] = [[IMLogUtils currentLogFilePath] lastPathComponent];
        stats[@"总日志文件数"] = @([IMLogUtils allLogFilePaths].count);
        stats[@"日志文件总大小"] = [NSString stringWithFormat:@"%.2f MB", [IMLogUtils totalLogFileSize] / 1024.0 / 1024.0];
    }
    
    // 过滤统计
    if (self.visibleLogTags) {
        stats[@"标签过滤数量"] = @(self.visibleLogTags.count);
    } else {
        stats[@"标签过滤"] = @"无";
    }
    
    return [stats copy];
}

#pragma mark - Private IMLog Methods



- (BOOL)shouldDisplayLogLine:(NSString *)line {
    // 基本的日志级别和标签过滤逻辑
    // 这里可以根据IMLogUtils的日志格式进行更精确的解析
    
    // 修正的级别检查（基于关键词）
    // IMLogLevel: Verbose=0, Debug=1, Info=2, Warning=3, Error=4
    // 只显示级别 >= minimumLogLevel 的日志
    if ([line containsString:@"VERBOSE"] && IMLogLevelVerbose < self.minimumLogLevel) return NO;
    if ([line containsString:@"DEBUG"] && IMLogLevelDebug < self.minimumLogLevel) return NO;
    if ([line containsString:@"INFO"] && IMLogLevelInfo < self.minimumLogLevel) return NO;
    if ([line containsString:@"WARNING"] && IMLogLevelWarning < self.minimumLogLevel) return NO;
    if ([line containsString:@"ERROR"] && IMLogLevelError < self.minimumLogLevel) return NO;
    
    // 标签过滤
    if (self.visibleLogTags) {
        BOOL tagMatched = NO;
        for (NSNumber *tagNum in self.visibleLogTags) {
            NSString *tagName = [NSString stringWithFormat:@"Tag_%@", tagNum];
            if ([line containsString:tagName]) {
                tagMatched = YES;
                break;
            }
        }
        if (!tagMatched) return NO;
    }
    
    return YES;
}

- (void)addFormattedLogLine:(NSString *)line {
    // 根据格式化选项处理日志行
    NSString *formattedLine = line;
    
    if (!self.showTimestamp) {
        // 移除时间戳（简化处理）
        NSRegularExpression *timeRegex = [NSRegularExpression regularExpressionWithPattern:@"^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}\\s*" options:0 error:nil];
        formattedLine = [timeRegex stringByReplacingMatchesInString:formattedLine options:0 range:NSMakeRange(0, formattedLine.length) withTemplate:@""];
    }
    
    if (!self.showThread) {
        // 移除线程信息
        NSRegularExpression *threadRegex = [NSRegularExpression regularExpressionWithPattern:@"\\[\\w+\\]\\s*" options:0 error:nil];
        formattedLine = [threadRegex stringByReplacingMatchesInString:formattedLine options:0 range:NSMakeRange(0, formattedLine.length) withTemplate:@""];
    }
    
    [self addLogMessage:formattedLine];
}



@end
